//本代码由汪碧康编写于2014年12月17日
//pconline.com.cn
//用于通过消息队列httpsqs或rabbitmq或者http请求的方式来清除apache traffic server中的缓存和cdn缓存
// mqac.go mesage queue clean ats cache
//v2.6

package main

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"flag"
	"fmt"
	"goconfig"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"runtime"
	"sort"
	"strings"
	"time"

	"github.com/bitly/go-simplejson"
	"github.com/streadway/amqp"
)

var cfpath = flag.String("f", "", "Specifies the configuration file path")

type Conf struct {
	ClsAtsCache     bool
	AtsIp           string
	ClsHcsCache     bool
	HcsIp           string
	MqType          string
	RbmqGetMsgMode  string //pull or subscribe
	RbmqIp          string
	RbmqAdmin       string
	RbmqPass        string
	RbmqVhost       string
	RbmqQueue       string
	CdnQueue        string //cdn queue
	HttpsqsIp       string
	HttpsqsQueue    string
	HttpPort        string
	ExchangeName    string
	RouteKey        string
	MaxMessage      int64
	CdnMaxMessage   int64
	ReadInterval    int64
	CdnCleanCache   bool
	CdnCompany      string //cdn gongsi
	DiLianApi       string //dilian api
	LoginToken      string //dilian logintoken
	BaiShanYunApi   string //baishanyun api
	BaiShanYunToken string //baishanyun token
	CdnInterfaceUrl string //wangsu api
	PushUser        string //wangsu user
	PushPasswd      string //wangsu passwd
	ClsInterval     int64
	ProxyAdress     string
}

type MqInfo struct {
	LogId int      `json:"logId"`
	Urls  []string `json:"urls"`
}

//ana mqinfo json
func Jsoninfo(mq string) []string {
	var mf MqInfo
	if err := json.Unmarshal([]byte(mq), &mf); err != nil {
		return nil
	}
	return mf.Urls
}

//getconfig
func GetConfig() (c *Conf) {
	flag.Parse()
	gr, err := goconfig.ReadConfigFile(*cfpath)
	if err != nil {
		fmt.Println("ERR:load etc/mqcac.conf config filure!")
		os.Exit(1)
	}
	c = &Conf{}
	var Section string = "GLOBAL"
	var err2 error
	c.ClsAtsCache, _ = gr.GetBool(Section, "ClsAtsCache")
	c.AtsIp, _ = gr.GetString(Section, "AtsIp")
	c.ClsHcsCache, _ = gr.GetBool(Section, "ClsHcsCache")
	c.HcsIp, _ = gr.GetString(Section, "HcsIp")
	c.MqType, _ = gr.GetString(Section, "MqType")
	c.RbmqGetMsgMode, _ = gr.GetString(Section, "RbmqGetMsgMode")
	if c.RbmqGetMsgMode != "pull" && c.RbmqGetMsgMode != "subscribe" {
		c.RbmqGetMsgMode = "subscribe"
	}
	c.RbmqIp, _ = gr.GetString(Section, "RbmqIp")
	c.RbmqAdmin, _ = gr.GetString(Section, "RbmqAdmin")
	c.RbmqPass, _ = gr.GetString(Section, "RbmqPass")
	c.RbmqVhost, _ = gr.GetString(Section, "RbmqVhost")
	c.RbmqQueue, _ = gr.GetString(Section, "RbmqQueue")
	c.CdnQueue, _ = gr.GetString(Section, "CdnQueue") //cdn queue
	c.ExchangeName, _ = gr.GetString(Section, "ExchangeName")
	c.RouteKey, _ = gr.GetString(Section, "RouteKey")

	c.MaxMessage, _ = gr.GetInt64(Section, "MaxMessage")
	if c.MaxMessage <= 0 {
		c.MaxMessage = 2
	}

	c.CdnMaxMessage, _ = gr.GetInt64(Section, "CdnMaxMessage")
	if c.CdnMaxMessage <= 0 {
		c.CdnMaxMessage = 20
	}

	c.CdnCleanCache, _ = gr.GetBool(Section, "CdnCleanCache")

	c.CdnCompany, _ = gr.GetString(Section, "CdnCompany")

	c.DiLianApi, _ = gr.GetString(Section, "DiLianApi")   //dilian
	c.LoginToken, _ = gr.GetString(Section, "LoginToken") //dilian

	c.BaiShanYunApi, _ = gr.GetString(Section, "BaiShanYunApi")     //baishanyun
	c.BaiShanYunToken, _ = gr.GetString(Section, "BaiShanYunToken") //baishanyun

	c.CdnInterfaceUrl, _ = gr.GetString(Section, "CdnInterfaceUrl") //wangsu
	c.PushUser, _ = gr.GetString(Section, "PushUser")               //wangsu
	c.PushPasswd, _ = gr.GetString(Section, "PushPasswd")           //wangsu
	c.ProxyAdress, _ = gr.GetString(Section, "ProxyAdress")

	c.ReadInterval, _ = gr.GetInt64(Section, "ReadInterval")
	if c.ReadInterval <= 0 {
		c.ReadInterval = 500
	}

	c.ClsInterval, _ = gr.GetInt64(Section, "ClsInterval")
	if c.ClsInterval <= 0 {
		c.ClsInterval = 30
	}

	c.HttpsqsIp, _ = gr.GetString(Section, "HttpsqsIp")
	c.HttpsqsQueue, _ = gr.GetString(Section, "HttpsqsQueue")

	c.HttpPort, err2 = gr.GetString(Section, "HttpPort")
	if err2 != nil {
		log.Printf("ERR:GetConfig failure,err%s:", err2)
	} else {
		if len(c.HttpPort) <= 0 {
			c.HttpPort = "8800"
		}
	}
	return c
}

//string to md5
func StrtoMd5(str string) string {
	h := md5.New()
	h.Write([]byte(str))
	x := h.Sum(nil)
	cc := hex.EncodeToString(x)
	return cc
}

//proxy is atsip
func GetByProxy(url_addr, proxy_addr, method string) (*http.Response, error) {
	proxy_addr = "http://" + proxy_addr
	request, _ := http.NewRequest(method, url_addr, nil)
	request.Header.Set("User-Agent", "pcauto-bbs(mqcac)")
	proxy, err := url.Parse(proxy_addr)
	if err != nil {
		return nil, err
		log.Printf("ERR:GetByProxy err,ip:%s,err:\n", proxy_addr, err)
	}
	client := &http.Client{
		Transport: &http.Transport{
			Proxy: http.ProxyURL(proxy),
			Dial: func(netw, proxy string) (net.Conn, error) {
				deadline := time.Now().Add(5 * time.Second)
				c, err := net.DialTimeout(netw, proxy, time.Second*5)
				if err != nil {
					return nil, err
				}
				c.SetDeadline(deadline)
				return c, nil
			},
		},
	}
	return client.Do(request)
}

//no proxy get url
func GetUrl(url string) (*http.Response, error) {
	request, _ := http.NewRequest("GET", url, nil)
	request.Header.Set("User-Agent", "pcauto-bbs(mqcac)")
	client := &http.Client{
		Transport: &http.Transport{
			Dial: func(netw, proxy string) (net.Conn, error) {
				deadline := time.Now().Add(10 * time.Second)
				c, err := net.DialTimeout(netw, proxy, time.Second*5)
				if err != nil {
					return nil, err
				}
				c.SetDeadline(deadline)
				return c, nil
			},
		},
	}
	return client.Do(request)
}

// get 请求URL
func ReqUrl(turl, methd, xhost string) (*http.Response, error) {
	request, _ := http.NewRequest(methd, turl, nil)
	request.Header.Set("User-Agent", "PConline-xcachetools")
	request.Host = xhost
	client := &http.Client{
		Transport: &http.Transport{
			Dial: func(netw, proxy string) (net.Conn, error) {
				deadline := time.Now().Add(10 * time.Second)
				c, err := net.DialTimeout(netw, proxy, time.Second*5)
				if err != nil {
					return nil, err
				}
				c.SetDeadline(deadline)
				return c, nil
			},
		},
	}
	return client.Do(request)
}

//wangsu clean CDN cache
func ClearCdn(proxyip, cdnintf, pushuser, pushpasswd string, xurl []string) {
	var allurl string
	for _, url := range xurl {
		uri := strings.TrimLeft(url, "http://")
		allurl = allurl + uri + ";"
	}
	turl := cdnintf + "username=" + pushuser + "&passwd=" + StrtoMd5(pushuser+pushpasswd+strings.TrimRight(allurl, ";")) + "&url=" + strings.TrimRight(allurl, ";")
	isproxy := (proxyip != "")
	var resp *http.Response
	var err error
	if isproxy {
		resp, err = GetByProxy(turl, proxyip, "GET")
	} else {
		resp, err = GetUrl(turl)
	}
	defer resp.Body.Close()
	if err != nil {
		log.Printf("ERR:GetUrl CDN failure!Error:", err)
		log.Printf("ERR:failure url :%s\n", turl)
		return
	} else {
		bodyBytes, _ := ioutil.ReadAll(resp.Body)
		bodycontent := string(bodyBytes)
		log.Printf("CDNINFO:%s,StatusCode=%d,uri=%s", bodycontent, resp.StatusCode, turl)
	}
}

//dilian clean CDN cache
func ClearDilian(proxyip, cdnintf, logintoken string, xurl []string) {
	var allurl string
	for _, url := range xurl {
		//uri := strings.TrimLeft(url, "http://")
		allurl = allurl + url + ","
	}
	turl := cdnintf + strings.TrimRight(allurl, ",") + "&loginToken=" + logintoken
	isproxy := (proxyip != "")
	var resp *http.Response
	var err error
	if isproxy {
		resp, err = GetByProxy(turl, proxyip, "GET")
	} else {
		resp, err = GetUrl(turl)
	}
	defer resp.Body.Close()
	if err != nil {
		log.Printf("ERR:GetUrl CDN failure!Error:", err)
		log.Printf("ERR:failure url :%s\n", turl)
		return
	} else {
		bodyBytes, _ := ioutil.ReadAll(resp.Body)
		bodycontent := string(bodyBytes)
		log.Printf("CDNINFO:%s,StatusCode=%d,uri=%s", bodycontent, resp.StatusCode, turl)
	}
}

//bai shan yun
type Ur struct {
	Urls []string `json:"urls"`
}

//bai shan yun
type Datainfo struct {
	Token  string `json:"token"`
	Method string `json:"method"`
	Params Ur     `json:"params"`
}

//baiyunshan proxy
func PostByProxy(url_addr, proxy_addr, method string, body *bytes.Reader) (*http.Response, error) {
	proxy_addr = "http://" + proxy_addr
	request, _ := http.NewRequest(method, url_addr, body)
	request.Header.Set("User-Agent", "pcauto-bbs(mqcac)")
	request.Header.Set("Content-Type", "application/json; charset=UTF-8")
	proxy, err := url.Parse(proxy_addr)
	if err != nil {
		return nil, err
		log.Printf("ERR:GetByProxy err,ip:%s,err:\n", proxy_addr, err)
	}
	client := &http.Client{
		Transport: &http.Transport{
			Proxy: http.ProxyURL(proxy),
			Dial: func(netw, proxy string) (net.Conn, error) {
				deadline := time.Now().Add(5 * time.Second)
				c, err := net.DialTimeout(netw, proxy, time.Second*5)
				if err != nil {
					return nil, err
				}
				c.SetDeadline(deadline)
				return c, nil
			},
		},
	}
	return client.Do(request)
}

//bai shan yun CDN
func ClearBaishan(proxyip, cdnintf, token string, xurl []string) {
	var D Datainfo
	var res *http.Response
	D.Token = token
	D.Method = "purge.add"
	D.Params = Ur{Urls: xurl}
	b, err := json.Marshal(D)
	if err != nil {
		fmt.Println("json err:", err)
	}
	//fmt.Println(string(b))
	body := bytes.NewBuffer([]byte(b))
	isproxy := (proxyip != "")
	if isproxy {
		res, err = PostByProxy(cdnintf, proxyip, "POST", bytes.NewReader([]byte(b)))
	} else {
		res, err = http.Post(cdnintf, "application/json;charset=utf-8", body)
	}
	result, err := ioutil.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		log.Println(err)
		return
	}
	//fmt.Printf("%s\n", result)
	js, _ := simplejson.NewJson(result)
	errno, _ := js.Get("errno").Int64()
	errmsg, _ := js.Get("errmsg").String()
	if errno == 0 {
		log.Printf("CDNINFO:success,uri=%s\n", xurl)
	} else {
		log.Printf("CDNINFO:Fail,errmsg:%s,uri=%s\n", errmsg, xurl)
	}
}

func ClearAts(tsip string, xurl string) {
	xip := strings.Split(strings.TrimSpace(tsip), ",")
	if len(xip) > 0 {
		for _, ip := range xip {
			resp, err := GetByProxy(xurl, ip, "PURGE")
			if err != nil {
				log.Printf("ERR:GetByProxy failure!Error:", err)
				log.Printf("ERR:failure ip :ip=%s,uri=%s\n", ip, xurl)
				continue
			} else {
				defer resp.Body.Close()
				switch {
				case resp.StatusCode == 200:
					log.Printf("INFO:Success %s,ip=%s\n", xurl, ip)
					return
				case resp.StatusCode == 404:
					log.Printf("INFO:NotFound %s,ip=%s\n", xurl, ip)
					return
				default:
					log.Printf("WARN:Failure,StatusCode=%d,atsip=%s,uri=%s", resp.StatusCode, ip, xurl)
				}
			}
		}
	}

}

//clshcs
func ClsHcs(tsip string, xurl string) {
	hip := strings.Split(strings.TrimSpace(tsip), ",")
	if len(hip) > 0 {
		for _, ip := range hip {
			i, err := url.Parse(xurl)
			if err != nil {
				return
			}
			uri := i.RequestURI()
			domain := i.Host
			hcsurl := "http://" + ip + uri
			resp, err := ReqUrl(hcsurl, "DELETE", domain)
			if err != nil {
				log.Printf("ERR:request failure %s\n", hcsurl)
				log.Printf("ERR:ReqUrl failure", err)
				continue
			} else {
				defer resp.Body.Close()
				switch resp.StatusCode {
				case 200:
					log.Printf("INFO:DelSuccess %s,ip=%s\n", hcsurl, ip)
					return
				case 404:
					log.Printf("INFO:NotFound %s,ip=%s\n", hcsurl, ip)
					return
				default:
					log.Printf("ERR:Failure %s,ip=%s\n", hcsurl, ip)
				}
			}
		}
	}
}

//数组去重去空
func RemoveDuplicatesAndEmpty(a []string) (ret []string) {
	a_len := len(a)
	for i := 0; i < a_len; i++ {
		if (i > 0 && a[i-1] == a[i]) || len(a[i]) == 0 {
			continue
		}
		ret = append(ret, a[i])
	}
	return
}

//get message form rabbitmq
func GetMessage(amqpURI, queueName, Routekey, Exchangename string, maxmsg int) (m []string, isok bool) {
	conn, err := amqp.Dial(amqpURI)
	if err != nil {
		log.Printf("ERR:Dial amqpURI failure!")
		return
	}
	defer func() {
		conn.Close()
	}()

	channel, err := conn.Channel()
	if err != nil {
		log.Printf("ERR:Conn Channel failure!")
		return
	}

	if err = channel.QueueBind(queueName, Routekey, Exchangename, false, nil); err != nil {
		log.Printf("ERR:Queue Bind failure,err: %s", err)
		return
	}
	//var isok bool = false
	for i := 0; i < maxmsg; i++ {
		msg, ok, err := channel.Get(queueName, false)
		if err != nil {
			log.Printf("ERR:Queue Get failure!:%s", err)
			return
		}
		if ok {
			msg.Reject(false)
			//t1 := strings.Split(string(msg.Body), ",")
			//m = append(m, t1...)
			t1 := Jsoninfo(string(msg.Body))
			m = append(m, t1...)
			if len(m) > 0 && m != nil {
				isok = true
			} else {
				isok = false
			}
		} else {
			break
		}
	}
	sort.Strings(m)
	//m = RemoveDuplicatesAndEmpty(m)
	return RemoveDuplicatesAndEmpty(m), isok

}

func BytesToString(b *[]byte) *string {
	s := bytes.NewBuffer(*b)
	r := s.String()
	return &r
}

//receive message form rabbitmq
func ConnRbmq(amqpURI, queueName, Exchangename string) (msgs <-chan amqp.Delivery) {
	conn, err := amqp.Dial(amqpURI)
	if err != nil {
		log.Printf("ERR:Dial amqpURI failure!")
		return
	}
	channel, err := conn.Channel()
	if err != nil {
		log.Printf("ERR:Conn Channel failure!")
		return
	}
	msgs, err = channel.Consume(queueName, "", true, false, false, false, nil)
	if err != nil {
		log.Printf("ERR:Channel Consume failure,err: %s", err)
		return
	}
	return msgs
}

//get msg from httpsqs
func GetHttpsqsMsg(HttpsqsIp, PoolName string) (m []string, isok bool) {
	Url := "http://" + HttpsqsIp + "/?name=" + PoolName + "&opt=get"
	client := new(http.Client)
	reg, err := http.NewRequest("GET", Url, nil)
	if err != nil {
		log.Printf("ERR:Read httpsqs failure! err:%s\n", err)
		return
	}
	reg.Header.Set("Connection", "keep-alive")
	resp, err := client.Do(reg)
	if err != nil {
		log.Printf("ERR:Client.do failure! err:%s\n", err)
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("ERR:get body failure! err:%s\n", err)
		return
	}
	if string(body) != "HTTPSQS_GET_END" {
		m = strings.Split(string(body), ",")
		if len(m) > 0 {
			isok = true
		} else {
			isok = false
		}
	}
	return
}

func Handler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	if r.Method == "GET" {
		v := GetConfig()
		durl := r.Form.Get("url")
		//durl := r.FormValue("url")
		xurl := strings.Split(durl, ",")
		if len(xurl) > 0 {
			if v.ClsAtsCache {
				log.Printf("WINFO:%s", xurl)
				xip := strings.Split(v.AtsIp, ";")
				for _, ip := range xip {
					for _, uri := range xurl {
						go ClearAts(ip, uri)
					}
				}
			}
			if v.CdnCleanCache {
				if v.CdnCompany == "wangsu" {
					ClearCdn(v.ProxyAdress, v.CdnInterfaceUrl, v.PushUser, v.PushPasswd, xurl)
				} else if v.CdnCompany == "dilian" {
					ClearDilian(v.ProxyAdress, v.DiLianApi, v.LoginToken, xurl)
				} else if v.CdnCompany == "baishanyun" {
					ClearBaishan(v.ProxyAdress, v.BaiShanYunApi, v.BaiShanYunToken, xurl)
				} else {
					log.Printf("ERR:unsupport the CDN:%s,can't start\n", v.CdnCompany)
					os.Exit(-1)
				}
			}
			io.WriteString(w, "success\n")
		}
	}
}

func main() {
	v := GetConfig()
	RbmqUri := "amqp://" + v.RbmqAdmin + ":" + v.RbmqPass + "@" + v.RbmqIp + "/" + v.RbmqVhost
	xip := strings.Split(v.AtsIp, ";")
	hip := strings.Split(v.HcsIp, ";")
	MaxMessage := int(v.MaxMessage)
	CdnMaxMessage := int(v.CdnMaxMessage)
	ReadInterval := time.Duration(v.ReadInterval)
	ClsInterval := time.Duration(v.ClsInterval)
	httpport := ":" + v.HttpPort

	CdnInterval := time.NewTicker(ClsInterval * time.Second).C
	AtsInterval := time.NewTicker(ReadInterval * time.Millisecond).C

	//var over = make(chan int, 10)
	NCPU := runtime.NumCPU()
	runtime.GOMAXPROCS(NCPU)
	var xurl []string
	var yes bool
	//var xurl = []string{"http://bbs.pcauto.com.cn/topic-6044255.html"}
	//var xurl = []string{"http://bbs.pcauto.com.cn/topic-6044255.html", "http://bbs.pcauto.com.cn/topic-604423.html"}

	if v.MqType == "rabbitmq" {
		if v.CdnCleanCache {
			for i := 0; i < NCPU; i++ {
				go func() {
					for {
						select {
						case <-CdnInterval:
							xurl, yes = GetMessage(RbmqUri, v.CdnQueue, v.RouteKey, v.ExchangeName, CdnMaxMessage)
							if yes {
								if v.CdnCompany == "wangsu" {
									ClearCdn(v.ProxyAdress, v.CdnInterfaceUrl, v.PushUser, v.PushPasswd, xurl)
								} else if v.CdnCompany == "dilian" {
									ClearDilian(v.ProxyAdress, v.DiLianApi, v.LoginToken, xurl)
								} else if v.CdnCompany == "baishanyun" {
									ClearBaishan(v.ProxyAdress, v.BaiShanYunApi, v.BaiShanYunToken, xurl)
								} else {
									log.Printf("ERR:unsupport the CDN:%s,can't start\n", v.CdnCompany)
									os.Exit(-1)
								}
							}
						}

					}
				}()
			}
		}

		if v.ClsAtsCache {
			if v.RbmqGetMsgMode == "subscribe" {
				msg := ConnRbmq(RbmqUri, v.RbmqQueue, v.ExchangeName)
				for i := 0; i < NCPU; i++ {
					go func() {
						for d := range msg {
							s := BytesToString(&(d.Body))
							//xurl = strings.Split(*s, ",")
							xurl := Jsoninfo(string(*s))
							log.Printf("XINFO:%s", xurl)
							if len(xurl) > 0 && xurl != nil {
								for _, ip := range xip {
									for _, url := range xurl {
										go ClearAts(ip, url)
									}
								}
							}

						}
					}()
				}
			} else if v.RbmqGetMsgMode == "pull" {
				for i := 0; i < NCPU; i++ {
					go func() {
						for {
							select {
							case <-AtsInterval:
								xurl, yes = GetMessage(RbmqUri, v.RbmqQueue, v.RouteKey, v.ExchangeName, MaxMessage)
								if yes {
									log.Printf("XINFO:%s", xurl)
									for _, ip := range xip {
										for _, url := range xurl {
											go ClearAts(ip, url)
										}
									}
								}
							}
						}
					}()
				}
			} else {
				log.Printf("ERR:unsupport the Get Rbmq message mode:%s,can't start\n", v.RbmqGetMsgMode)
				os.Exit(-1)
			}
		}

		if v.ClsHcsCache {
			if v.RbmqGetMsgMode == "subscribe" {
				msg := ConnRbmq(RbmqUri, v.RbmqQueue, v.ExchangeName)
				for i := 0; i < NCPU; i++ {
					go func() {
						for d := range msg {
							s := BytesToString(&(d.Body))
							//xurl = strings.Split(*s, ",")
							xurl := Jsoninfo(string(*s))
							log.Printf("XINFO:%s", xurl)
							if len(xurl) > 0 && xurl != nil {
								for _, ip := range hip {
									for _, url := range xurl {
										go ClsHcs(ip, url)
									}
								}
							}

						}
					}()
				}
			} else if v.RbmqGetMsgMode == "pull" {
				for i := 0; i < NCPU; i++ {
					go func() {
						for {
							select {
							case <-AtsInterval:
								xurl, yes = GetMessage(RbmqUri, v.RbmqQueue, v.RouteKey, v.ExchangeName, MaxMessage)
								if yes {
									log.Printf("XINFO:%s", xurl)
									for _, ip := range hip {
										for _, url := range xurl {
											go ClsHcs(ip, url)
										}
									}
								}
							}
						}
					}()
				}
			} else {
				log.Printf("ERR:unsupport the Get Rbmq message mode:%s,can't start\n", v.RbmqGetMsgMode)
				os.Exit(-1)
			}
		}

	} else if v.MqType == "httpsqs" {
		if v.CdnCleanCache {
			for i := 0; i < NCPU; i++ {
				go func() {
					for {
						select {
						case <-CdnInterval:
							xurl, yes = GetHttpsqsMsg(v.HttpsqsIp, v.HttpsqsQueue)
							if yes {
								if v.CdnCompany == "wangsu" {
									ClearCdn(v.ProxyAdress, v.CdnInterfaceUrl, v.PushUser, v.PushPasswd, xurl)
								} else if v.CdnCompany == "dilian" {
									ClearDilian(v.ProxyAdress, v.DiLianApi, v.LoginToken, xurl)
								} else if v.CdnCompany == "baishanyun" {
									ClearBaishan(v.ProxyAdress, v.BaiShanYunApi, v.BaiShanYunToken, xurl)
								} else {
									log.Printf("ERR:unsupport the CDN:%s,can't start\n", v.CdnCompany)
									os.Exit(-1)
								}
							}
						}

					}
				}()
			}
		}
		if v.ClsAtsCache {
			for i := 0; i < NCPU; i++ {
				go func() {
					for {
						select {
						case <-AtsInterval:
							xurl, yes = GetHttpsqsMsg(v.HttpsqsIp, v.HttpsqsQueue)
							if yes {
								log.Printf("XINFO:%s", xurl)
								for _, ip := range xip {
									for _, url := range xurl {
										go ClearAts(ip, url)
									}
								}
							}
						}
					}
				}()
			}
		}
		if v.ClsHcsCache {
			for i := 0; i < NCPU; i++ {
				go func() {
					for {
						select {
						case <-AtsInterval:
							xurl, yes = GetHttpsqsMsg(v.HttpsqsIp, v.HttpsqsQueue)
							if yes {
								log.Printf("XINFO:%s", xurl)
								for _, ip := range xip {
									for _, url := range xurl {
										go ClsHcs(ip, url)
									}
								}
							}
						}
					}
				}()
			}
		}
	} else {
		log.Printf("ERR:unsupport the mqtype:%s,only use http!\n", v.MqType)
		//os.Exit(-1)
	}

	http.HandleFunc("/", Handler)
	err1 := http.ListenAndServe(httpport, nil)
	if err1 != nil {
		log.Fatal("ERR:ListenAndServe: ", err1)
	}

}
